// RealtimeCollect.cpp : implementation file
//

#include "stdafx.h"
#include "../Frame/GYWalkAidApp.h"
#include "RealtimeCollect.h"
#include "../Gait/GaitAnaly.h"
#include "../Common/CommonDef.h"
#include "../Common/CommonFun.h"
#include "../Common/GYDataSet.h"
#include "../PatientMan/PatMan.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static CRealtimeCollect* s_pThis = NULL;

static CWnd* s_pCurTimeLabel	= NULL;
static CWnd* s_pDevCountLabel	= NULL;
static CWnd* s_pConnectInfo		= NULL;

/////////////////////////////////////////////////////////////////////////////
// CRealtimeCollect dialog
static struct
{
	DWORD				dwLabelId;
	CWnd*				pLabel;
	DWORD				dwSnapButtonId;
	CWnd*				pSnapButton;
	DWORD				dwProgressLabelId;
	CWnd*				pProgressLabel;
	DWORD				dwMRNCode;
	CGaitAnaly*			pGait;
	int					nWAIndex;
}
s_aLabels[] = 
{
	{IDC_STATIC_MONITOR1,	NULL,	IDC_BUTTON_SNAP1,	NULL,	IDC_STATIC_PROGRESS1,	NULL,	0,	NULL,	-1},
	{IDC_STATIC_MONITOR2,	NULL,	IDC_BUTTON_SNAP2,	NULL,	IDC_STATIC_PROGRESS2,	NULL,	0,	NULL,	-1},
	{IDC_STATIC_MONITOR3,	NULL,	IDC_BUTTON_SNAP3,	NULL,	IDC_STATIC_PROGRESS3,	NULL,	0,	NULL,	-1},
	{IDC_STATIC_MONITOR4,	NULL,	IDC_BUTTON_SNAP4,	NULL,	IDC_STATIC_PROGRESS4,	NULL,	0,	NULL,	-1},
	{IDC_STATIC_MONITOR5,	NULL,	IDC_BUTTON_SNAP5,	NULL,	IDC_STATIC_PROGRESS5,	NULL,	0,	NULL,	-1},
};

CRealtimeCollect::CRealtimeCollect(CWnd* pParent /*=NULL*/)
	: CDialog(CRealtimeCollect::IDD, pParent)
{
	//{{AFX_DATA_INIT(CRealtimeCollect)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

BEGIN_MESSAGE_MAP(CRealtimeCollect, CDialog)
	//{{AFX_MSG_MAP(CRealtimeCollect)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_EXIT_RT, OnButtonExit)
	ON_BN_CLICKED(IDC_BUTTON_SNAP1, OnButtonSnap1)
	ON_BN_CLICKED(IDC_BUTTON_SNAP2, OnButtonSnap2)
	ON_BN_CLICKED(IDC_BUTTON_SNAP3, OnButtonSnap3)
	ON_BN_CLICKED(IDC_BUTTON_SNAP4, OnButtonSnap4)
	ON_BN_CLICKED(IDC_BUTTON_SNAP5, OnButtonSnap5)
	ON_BN_CLICKED(IDC_BUTTON_SEARCH_WA, OnButtonSearchWa)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRealtimeCollect message handlers

BOOL CRealtimeCollect::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	s_pThis				= this;
	s_pCurTimeLabel		= GetDlgItem(IDC_STATIC_CUR_TIME);
	s_pDevCountLabel	= GetDlgItem(IDC_STATIC_DEV_COUNT);
	s_pConnectInfo		= GetDlgItem(IDC_STATIC_CONN_INFO);

	CCustomMsgCenter* pMsgCenter = GetApp()->GetCustMsgCenter();
	if(pMsgCenter)
	{
		pMsgCenter->RegCustomMsgProcess(GYWA_MSG_BLUETOOTH_FOUND_NEWDEV,	this,	(MSG_PROCESS_FUNC)OnAddGaitGraph);
		pMsgCenter->RegCustomMsgProcess(GYWA_MSG_BLUETOOTH_REMOVE_DEV,		this,	(MSG_PROCESS_FUNC)OnDelGaitGraph);
		pMsgCenter->RegCustomMsgProcess(GYWA_MSG_BLUETOOTH_CONNECT_PROGRESS,this,	(MSG_PROCESS_FUNC)OnConnectProgress);
		pMsgCenter->RegTimerProcess(	GYWA_MSG_REALTIME_TIMERID_SHOWTIME,	this,	(MSG_PROCESS_FUNC)OnTimerShowTime);

		pMsgCenter->StartTimer(			GYWA_MSG_REALTIME_TIMERID_SHOWTIME,	1000);
	}

	CWAManager* pBTMan = GetApp()->GetWAMan();
	int nIndex = pBTMan->GetFirstDevIndex();

	for(int i = 0; i < ARRAY_ELE_COUNT(s_aLabels); i++)
	{
		s_aLabels[i].pSnapButton		= GetDlgItem(s_aLabels[i].dwSnapButtonId);
		s_aLabels[i].pLabel				= GetDlgItem(s_aLabels[i].dwLabelId);
		s_aLabels[i].pProgressLabel		= GetDlgItem(s_aLabels[i].dwProgressLabelId);
		s_aLabels[i].pGait = NULL;

		if(nIndex >= 0)
		{
			if(pBTMan->IsWAConnected(nIndex))
			{
				DWORD dwCommVer = pBTMan->GetWACommVersion(nIndex);

				if(s_aLabels[i].pSnapButton && ::IsWindow(s_aLabels[i].pSnapButton->GetSafeHwnd()))
					s_aLabels[i].pSnapButton->EnableWindow(dwCommVer >= 0x12);

				if(dwCommVer >= 0x12)
				{
					int nReadTimes = 0;
					DWORD dwMRNCode = 0;

					while((dwMRNCode == 0 || dwMRNCode == 0x3fff) && nReadTimes < MAX_WRITE_PARAM_TIMES)
					{
						dwMRNCode = pBTMan->cmdReadMRNCode(nIndex);

						if(dwMRNCode != 0 && dwMRNCode != 0x3fff)
						{
							break;
						}
						else
						{
							nReadTimes++;
							if(nReadTimes < MAX_WRITE_PARAM_TIMES)
								Sleep(300);
						}
					}

					s_aLabels[i].dwMRNCode = dwMRNCode;
				}
			}
			else
			{
				ASSERT(s_aLabels[i].pProgressLabel);
				if(s_aLabels[i].pProgressLabel && ::IsWindow(s_aLabels[i].pProgressLabel->GetSafeHwnd()))
					s_aLabels[i].pProgressLabel->ShowWindow(SW_SHOW);
			}
			
			s_aLabels[i].nWAIndex = nIndex;
			s_aLabels[i].pGait = new CGaitAnaly(s_aLabels[i].pLabel, nIndex);
			s_aLabels[i].pGait->StartDraw();

			nIndex = pBTMan->GetNextDevIndex(nIndex);
		}
	}

	OnTimerShowTime(NULL, NULL);
	ShowDevCount();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CRealtimeCollect::OnDestroy() 
{
	s_pCurTimeLabel		= NULL;
	s_pDevCountLabel	= NULL;
	s_pConnectInfo		= NULL;

	CDialog::OnDestroy();
}

void CRealtimeCollect::OnAddGaitGraph(WPARAM wParam, LPARAM lParam)
{
	CWAManager* pBTMan = GetApp()->GetWAMan();

	for(int j = 0; j < ARRAY_ELE_COUNT(s_aLabels); j++)
	{
		if(s_aLabels[j].pGait)
		{
			if(s_aLabels[j].nWAIndex == wParam)
			{
				DWORD dwCommVer = pBTMan->GetWACommVersion(wParam);
				
				if(s_aLabels[j].pSnapButton && ::IsWindow(s_aLabels[j].pSnapButton->GetSafeHwnd()))
					s_aLabels[j].pSnapButton->EnableWindow(dwCommVer >= 0x12);
				
				if(dwCommVer >= 0x12)
					s_aLabels[j].dwMRNCode = pBTMan->cmdReadMRNCode(wParam);

				ASSERT(s_aLabels[j].pProgressLabel);

				if(s_aLabels[j].pProgressLabel && ::IsWindow(s_aLabels[j].pProgressLabel->GetSafeHwnd()))
					s_aLabels[j].pProgressLabel->ShowWindow(SW_HIDE);

				return;
			}
		}
	}

	for(int i = 0; i < ARRAY_ELE_COUNT(s_aLabels); i++)
	{
		if(s_aLabels[i].pGait == NULL)
		{
			ASSERT(s_aLabels[i].pProgressLabel);
			if(s_aLabels[i].pProgressLabel && ::IsWindow(s_aLabels[i].pProgressLabel->GetSafeHwnd()))
				s_aLabels[i].pProgressLabel->ShowWindow(SW_HIDE);

			DWORD dwCommVer = pBTMan->GetWACommVersion(wParam);

			DWORD dwMRNCode = 0;
			if(dwCommVer >= 0x12)
				dwMRNCode = pBTMan->cmdReadMRNCode(wParam);

			if(s_aLabels[i].pSnapButton && ::IsWindow(s_aLabels[i].pSnapButton->GetSafeHwnd()))
				s_aLabels[i].pSnapButton->EnableWindow(dwCommVer >= 0x12);

			s_aLabels[i].dwMRNCode = dwMRNCode;
			s_aLabels[i].pGait = new CGaitAnaly(s_aLabels[i].pLabel, wParam);
			s_aLabels[i].pGait->StartDraw();
			s_aLabels[i].nWAIndex = wParam;

			break;
		}
	}
	
	s_pThis->SetTimer(GYWA_MSG_REALTIME_TIMERID_REFRESH_WACOUNT, 1000, RefreshWACountTimerFunc);
}

void CRealtimeCollect::OnDelGaitGraph(WPARAM wParam, LPARAM lParam)
{
	for(int i = 0; i < ARRAY_ELE_COUNT(s_aLabels); i++)
	{
		if(s_aLabels[i].nWAIndex == wParam)
		{
			if(s_aLabels[i].pSnapButton && ::IsWindow(s_aLabels[i].pSnapButton->GetSafeHwnd()))
				s_aLabels[i].pSnapButton->EnableWindow(FALSE);

			s_aLabels[i].nWAIndex = -1;
			s_aLabels[i].pGait->StopDraw();
			SAFE_DELETE(s_aLabels[i].pGait);
			
			break;
		}
	}

	s_pThis->SetTimer(GYWA_MSG_REALTIME_TIMERID_REFRESH_WACOUNT, 1000, RefreshWACountTimerFunc);
}

void CRealtimeCollect::OnTimerShowTime(WPARAM wParam, LPARAM lParam)
{
	CTime curTime = CTime::GetCurrentTime();
	CString strCurTime;
	strCurTime.Format(_T("%4d-%02d-%02d %02d:%02d:%02d"),	curTime.GetYear(),	curTime.GetMonth(),		curTime.GetDay(),
															curTime.GetHour(),	curTime.GetMinute(),	curTime.GetSecond());
	if(s_pCurTimeLabel && ::IsWindow(s_pCurTimeLabel->GetSafeHwnd()))
		s_pCurTimeLabel->SetWindowText(strCurTime);

	//  refresh dev count per 5 seconds
	static DWORD s_dwTotalSecnod = 0;
	s_dwTotalSecnod++;
	if((s_dwTotalSecnod%5) == 0)
		ShowDevCount();
}

void CRealtimeCollect::OnButtonExit() 
{
	CCustomMsgCenter* pMsgCenter = GetApp()->GetCustMsgCenter();
	if(pMsgCenter)
	{
		pMsgCenter->StopTimer(				GYWA_MSG_REALTIME_TIMERID_SHOWTIME);
		
		pMsgCenter->RemoveCustomMsgProcess(	GYWA_MSG_BLUETOOTH_FOUND_NEWDEV,	this,	(MSG_PROCESS_FUNC)OnAddGaitGraph);
		pMsgCenter->RemoveCustomMsgProcess(	GYWA_MSG_BLUETOOTH_REMOVE_DEV,		this,	(MSG_PROCESS_FUNC)OnDelGaitGraph);
		pMsgCenter->RemoveCustomMsgProcess(GYWA_MSG_BLUETOOTH_CONNECT_PROGRESS,	this,	(MSG_PROCESS_FUNC)OnConnectProgress);
		pMsgCenter->RemoveTimerProcess(		GYWA_MSG_REALTIME_TIMERID_SHOWTIME,	this,	(MSG_PROCESS_FUNC)OnTimerShowTime);
	}
	
	for(int i = 0; i < ARRAY_ELE_COUNT(s_aLabels); i++)
	{
		if(s_aLabels[i].pGait)
		{
			s_aLabels[i].nWAIndex = -1;
			s_aLabels[i].pGait->StopDraw();
			SAFE_DELETE(s_aLabels[i].pGait);
		}
	}

	CDialog::OnCancel();	
}

void CRealtimeCollect::ShowDevCount()
{
	CWAManager* pBTMan = GetApp()->GetWAMan();
	if(pBTMan == NULL)
	{
		ASSERT(pBTMan);
		return;
	}

	if(s_pDevCountLabel && ::IsWindow(s_pDevCountLabel->GetSafeHwnd()))
	{
		int nWADevCount = pBTMan->GetWADeviceCount();
		CString strDeCount;
		strDeCount.Format(_T("%d"), nWADevCount);
		s_pDevCountLabel->SetWindowText(strDeCount);
	}
}

void CRealtimeCollect::OnButtonSnap1() 
{
	GetSnap(0);
}

void CRealtimeCollect::OnButtonSnap2() 
{
	GetSnap(1);
}

void CRealtimeCollect::OnButtonSnap3() 
{
	GetSnap(2);
}

void CRealtimeCollect::OnButtonSnap4() 
{
	GetSnap(3);
}

void CRealtimeCollect::OnButtonSnap5() 
{
	GetSnap(4);
}

void CRealtimeCollect::GetSnap(int nIndex)
{
	if(s_aLabels[nIndex].pGait)
	{
		CWaitCursor wait;

		DWORD dwMRNCode = s_aLabels[nIndex].dwMRNCode;
		if(dwMRNCode == 0 || dwMRNCode == 0x3fff)
		{
			GYMsgBox(IDS_PAT_MRN_EMPTY, MB_ICONSTOP);
			return;
		}

 		CString strSQL;
		strSQL.Format(_T("SELECT MedicalRecordNo, DiagProgress FROM PatientInfo WHERE SerialNo=%d"), dwMRNCode);
		CGYDataSet setPatInfo(strSQL);
		if(setPatInfo.IsEOF())
		{
			CString strFormat = GetResString(IDS_RT_NO_PATIENT);
			CString strNoPatient;
			strNoPatient.Format(strFormat, dwMRNCode);

			GYMsgBox(strNoPatient, MB_ICONSTOP);
			return;
		}

		CString strMRN;
		setPatInfo.GetFieldValue(_T("MedicalRecordNo"), strMRN);

		CString strDiagProgress;
		setPatInfo.GetFieldValue(_T("DiagProgress"), strDiagProgress);
		setPatInfo.Close();

		int nProgress = _ttoi(strDiagProgress);
		if(nProgress < TAB_INDEX_1STDIAG)
		{
			CString strFormat = GetResString(IDS_RT_HAVE_NO_1STDIAG);
			CString strNo1stDiag;
			strNo1stDiag.Format(strFormat, strMRN);

			GYMsgBox(strNo1stDiag, MB_ICONSTOP);
			return;
		}

		strSQL.Format(_T("SELECT DiagSN, DiagDate, IsDraft FROM DiagRecord WHERE MedicalRecordNo='%s' ORDER BY DiagSN DESC LIMIT 1"), strMRN);
 		CGYDataSet setDiagRec(strSQL);
		if(setDiagRec.IsEOF())
		{
			CString strFormat = GetResString(IDS_RT_HAVE_NO_1STDIAG);
			CString strNo1stDiag;
			strNo1stDiag.Format(strFormat, strMRN);
			
			GYMsgBox(strNo1stDiag, MB_ICONSTOP);
			return;
		}

		CString strDiagSN;
		setDiagRec.GetFieldValue(_T("DiagSN"), strDiagSN);

		CString strDiagDate;
		setDiagRec.GetFieldValue(_T("DiagDate"), strDiagDate);
		
		CString strIsDraft;
		setDiagRec.GetFieldValue(_T("IsDraft"), strIsDraft);
		
		int nDiagSN = _ttoi(strDiagSN);
		strDiagDate = strDiagDate.Left(10);
		BOOL bIsDraft = (strIsDraft == _T("1"));

		CTime curTime = CTime::GetCurrentTime();
		CString strToday = curTime.Format(_T("%Y-%m-%d"));
		CString strCurTime;
		strCurTime.Format(_T("%4d-%02d-%02d %02d:%02d:%02d"), curTime.GetYear(), curTime.GetMonth(), curTime.GetDay(), curTime.GetHour(), curTime.GetMinute(), curTime.GetSecond());

		if(strToday == strDiagDate)
		{
			//  replace the old gait graph
			BOOL bRet = s_aLabels[nIndex].pGait->SnapGait(s_aLabels[nIndex].dwMRNCode, nDiagSN);
			if(bRet)
			{
				CString strDiag;
				if(nDiagSN == 0)
					strDiag = GetResString(IDS_QRY_1ST_DIAG);
				else
					strDiag.Format(_T("%s %s"), GetResString(IDS_TABTITLE_SUBSEDIAG), strDiagSN);

				CString strFormat = GetResString(IDS_RT_SNAP_SUCC);
				CString strSnapOK;
				strSnapOK.Format(strFormat, strMRN, strDiag);

				GYMsgBox(strSnapOK, MB_ICONINFORMATION);
			}

			return;
		}
		else
		{
			if(nDiagSN > 0 && bIsDraft)
			{
				CString strDiag;
				strDiag.Format(_T("%s %s"), GetResString(IDS_TABTITLE_SUBSEDIAG), strDiagSN);

				CString strFormat = GetResString(IDS_RT_TEMP_TO_REAL);
				CString strTempToReal;
				strTempToReal.Format(strFormat, strMRN, strDiag);

				if(GYMsgBox(strTempToReal, MB_ICONQUESTION|MB_YESNO) != IDYES)
					return;

				strSQL.Format(_T("UPDATE DiagRecord SET IsDraft=0 WHERE MedicalRecordNo='%s' AND DiagSN=%s"), strMRN, strDiagSN);
				if(!setDiagRec.ExecuteSQL(strSQL))
				{
					DataErrorMsgBox(__FILE__, __LINE__, strSQL, setDiagRec.GetLastErrorString());
					return;
				}

				strSQL.Format(_T("UPDATE BodyCheckReg SET IsDraft=0 WHERE MedicalRecordNo='%s' AND DiagSN=%s"), strMRN, strDiagSN);
				if(!setDiagRec.ExecuteSQL(strSQL))
				{
					DataErrorMsgBox(__FILE__, __LINE__, strSQL, setDiagRec.GetLastErrorString());
					return;
				}
			}

			CWAManager* pBTMan = GetApp()->GetWAMan();
			int nDevIndex = s_aLabels[nIndex].nWAIndex;
			CString strDevID = pBTMan->GetWADevID(nDevIndex);
			CString strBTAddress = pBTMan->GetWAAddress(nIndex);
			
			CString strUserName = GetApp()->GetUserName();
			int nNewDiagSN = nDiagSN + 1;

			//  New a gait graph
			BOOL bRet = s_aLabels[nIndex].pGait->SnapGait(s_aLabels[nIndex].dwMRNCode, nNewDiagSN);
			if(!bRet)
				return;
			
			//  Insert a diagnose record
			strSQL.Format(_T("INSERT INTO DiagRecord (MedicalRecordNo, DiagSN, DiagDate, UserName, IsDraft, UpTime, DownTime, StiOpen, StiClose, PulseFreq, PulseWidth, PulseCount, WADevID, WAAddress, DiagSummary) VALUES ('%s', %d,	'%s', '%s', 0, 0, 0, 0, 0, 0, 0, 0, '%s', '%s','')"),
							strMRN, nNewDiagSN, strCurTime, strUserName, strDevID, strBTAddress);

			if(!setDiagRec.ExecuteSQL(strSQL))
			{
				DataErrorMsgBox(__FILE__, __LINE__, strSQL, setDiagRec.GetLastErrorString());
				return;
			}
			
			CString strDiag;
			strDiag.Format(_T("%s %d"), GetResString(IDS_TABTITLE_SUBSEDIAG), nNewDiagSN);

			CString strFormat = GetResString(IDS_RT_SNAP_SUCC);
			CString strSnapOK;
			strSnapOK.Format(strFormat, strMRN, strDiag);
			
			GYMsgBox(strSnapOK, MB_ICONINFORMATION);
		}
	}
}

void CRealtimeCollect::OnButtonSearchWa() 
{
	CWAManager* pBTMan = GetApp()->GetWAMan();
	pBTMan->SearchWAImmediately();
}

void CRealtimeCollect::RefreshWACountTimerFunc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
	CRealtimeCollect* pThis = (CRealtimeCollect*)CRealtimeCollect::FromHandle(hWnd);
	if(pThis)
	{
		pThis->KillTimer(nIDEvent);
		pThis->ShowDevCount();
	}
}

void CRealtimeCollect::OnConnectProgress(WPARAM wParam, LPARAM lParam)
{
	DWORD dwShowDuration = lParam;
	if(dwShowDuration == 0)
		return;

	s_pThis->KillTimer(GYWA_MSG_REALTIME_TIMERID_HIDE_LABEL);
	
	// 'this' pointer is invalid, use static pointer to reference control in the dialog
	LPCTSTR pMsgInfo = (LPCTSTR)wParam;
	if(s_pConnectInfo && ::IsWindow(s_pConnectInfo->GetSafeHwnd()))
	{
		s_pConnectInfo->ShowWindow(SW_SHOW);
		s_pConnectInfo->SetWindowText(pMsgInfo);
	}
	
	if(dwShowDuration != INFINITE)
	{
		s_pThis->SetTimer(GYWA_MSG_REALTIME_TIMERID_HIDE_LABEL, dwShowDuration, HideLabelTimerFunc);
	}
}

void CRealtimeCollect::HideLabelTimerFunc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
	s_pThis->KillTimer(nIDEvent);

	if(s_pConnectInfo && ::IsWindow(s_pConnectInfo->GetSafeHwnd()))
		s_pConnectInfo->ShowWindow(SW_HIDE);
}
